﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Xml.Linq;
//
using PerceptiveMCAPI.Types.Internal;
//
namespace PerceptiveMCAPI.Types
{
   public class campaignsOutput : Api_BaseOutput
   {
      public List<campaignsResults> result { get; set; }
      public campaignsParms inputParms { get; private set; }
      // --------------------------------------------------------
      public campaignsOutput( campaignsInput input )
         : base( input )
      {
         inputParms = input.parms;
         result = new List<campaignsResults>();
      }
      // --------------------------------------------------- tostring
      public override string ToString()
      {
         return string.Format( "Campaign count: {0}", this.result.Count );
      }

      #region ================================================================== format setup

      // ---- serial
      internal void Format( string api_Request, string api_Response )
      {
         this.api_Request = api_Request;
         this.api_Response = api_Response;
         // ----------------------------------
         if ( this.api_OutputType == EnumValues.OutputType.JSON )
            outputJSON();
         else if ( this.api_OutputType == EnumValues.OutputType.XML )
            outputXML();
      }

      // ---- xmlrpc
      internal void Format( x_campaigns[] rpcResult )
      {
         this.api_Request = EnumValues.NotSupplied;
         this.api_Response = EnumValues.NotSupplied;
         // ------------------------
         this.result = FormatResults( rpcResult );
      }

      #endregion

      #region ================================================================= Output

      // ---------------------------------------------------------- outputXML
      private void outputXML()
      {
         XElement xml = XElement.Parse( this.api_Response );
         // error check
         Api_Error error = apiSerial.GetXmlOutputError( xml );
         if ( error != null )
         {
            this.api_ErrorMessages.Add( error );
            return;
         }
         // -------------------------------------------- get values
         int i; Int64 i64; DateTime dt;
         try
         {
            IEnumerable<XElement> campaigns = xml.Elements( "struct" );
            foreach ( XElement campaign in campaigns )
            {
               campaignsResults cr = new campaignsResults();
               // ----------------------------------
               cr.id = campaign.Element( "id" ).Value;
               int.TryParse( campaign.Element( "web_id" ).Value, out i );
               cr.web_id = i;
               cr.list_id = campaign.Element( "list_id" ).Value;
               Int64.TryParse( campaign.Element( "folder_id" ).Value, out i64 );
               cr.folder_id = i64;
               cr.title = campaign.Element( "title" ).Value;
               cr.type = apiHelper.GetEnumFromString<EnumValues.campaign_type>( campaign.Element( "type" ).Value );
               DateTime.TryParse( campaign.Element( "create_time" ).Value, out dt );
               cr.create_time = dt;
               DateTime.TryParse( campaign.Element( "send_time" ).Value, out dt );
               cr.send_time = dt;
               cr.status = apiHelper.GetEnumFromString<EnumValues.campaign_status>( campaign.Element( "status" ).Value );
               cr.from_name = campaign.Element( "from_name" ).Value;
               cr.from_email = campaign.Element( "from_email" ).Value;
               cr.subject = campaign.Element( "subject" ).Value;
               cr.to_email = campaign.Element( "to_email" ).Value;
               cr.archive_url = campaign.Element( "archive_url" ).Value;
               int.TryParse( campaign.Element( "emails_sent" ).Value, out i );
               cr.emails_sent = i;
               cr.inline_css = ( campaign.Element( "inline_css" ).Value.Trim() == "Y" ) ? true : false;
               // --------------------------- v1.2.2
               cr.analytics = campaign.Element( "analytics" ).Value;
               cr.analytics_tag = campaign.Element( "analytics_tag" ).Value;
               cr.track_opens = campaign.Element( "track_opens" ).Value.Trim() == "1" ? true : false;
               cr.track_clicks_html = campaign.Element( "track_clicks_html" ).Value.Trim() == "1" ? true : false;
               cr.track_clicks_text = campaign.Element( "track_clicks_text" ).Value.Trim() == "1" ? true : false;
               cr.segment_text = campaign.Element( "segment_text" ).Value;
               // --------------------------- v1.2.6/7
               cr.authenticate = campaign.Element( "authenticate" ).Value.Trim() == "1" ? true : false;
               cr.ecomm360 = campaign.Element( "ecomm360" ).Value.Trim() == "1" ? true : false;
               cr.auto_tweet = campaign.Element( "auto_tweet" ).Value.Trim() == "1" ? true : false;
               cr.timewarp = campaign.Element( "timewarp" ).Value.Trim() == "1" ? true : false;
               // ---------------------------
               XElement so = campaign.Element( "segment_opts" );
               if ( so.HasElements )
               {
                  cr.segment_opts.match = so.Element( "match" ).Value;
                  IEnumerable<XElement> cond = so.Elements( "conditions" ).Descendants( "struct" );
                  foreach ( XElement item in cond )
                  {
                     campaignSegmentCondition cso = new campaignSegmentCondition();
                     cso.field = item.Element( "field" ).Value;
                     cso.op = item.Element( "op" ).Value;
                     cso.value = item.Element( "value" ).Value;
                     cr.segment_opts.conditions.Add( cso );
                  }
               }
               // ---------------------------
               this.result.Add( cr );
            }
         }
         catch ( Exception ex )
         {
            this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
         }
      }

      // ---------------------------------------------------------- outputJSON
      private void outputJSON()
      {
         JavaScriptSerializer jss = new JavaScriptSerializer();

         try
         {
            if ( this.api_Response.Contains( EnumValues.JSONErrorString ) )
            {
               Api_Error err = jss.Deserialize<Api_Error>( this.api_Response );
               this.api_ErrorMessages.Add( err );
            }
            else
            {
               x_campaigns[] jsonResult = jss.Deserialize<x_campaigns[]>( this.api_Response );
               this.result = FormatResults( jsonResult );
            }
         }
         catch ( Exception ex )
         {
            this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
         }
      }

      // ----------------------------------------------------------------------------- FormatResults
      private List<campaignsResults> FormatResults( x_campaigns[] x_results )
      {
         List<campaignsResults> campaignList = new List<campaignsResults>();

         // array to generic list
         foreach ( x_campaigns tc in x_results )
         {
            DateTime dt;
            campaignsResults campaign = new campaignsResults();
            //
            campaign.id = tc.id;
            campaign.web_id = tc.web_id;
            campaign.list_id = tc.list_id;
            campaign.folder_id = (Int64)tc.folder_id;
            campaign.title = tc.title;
            campaign.type = apiHelper.GetEnumFromString<EnumValues.campaign_type>( tc.type );
            DateTime.TryParse( tc.create_time, out dt ); campaign.create_time = dt;
            DateTime.TryParse( tc.send_time, out dt ); campaign.send_time = dt;
            campaign.status = apiHelper.GetEnumFromString<EnumValues.campaign_status>( tc.status );
            campaign.from_name = tc.from_name;
            campaign.from_email = tc.from_email;
            campaign.subject = tc.subject;
            campaign.to_email = tc.to_email;
            campaign.archive_url = tc.archive_url;
            campaign.emails_sent = tc.emails_sent;
            campaign.inline_css = ( tc.inline_css == "Y" ) ? true : false;
            // --------------------------- v1.2.2
            campaign.analytics = tc.analytics;
            campaign.analytics_tag = tc.analytics_tag;
            campaign.track_opens = tc.track_opens;
            campaign.track_clicks_html = tc.track_clicks_html;
            campaign.track_clicks_text = tc.track_clicks_text;
            campaign.segment_text = tc.segment_text;
            // yes, there is text returned by MC, but sometimed I want it RAW!
            campaign.segment_opts = FormatSegmentOptions( tc.segment_opts );
            // --------------------------- v1.2.6/7
            campaign.authenticate = tc.authenticate;
            campaign.ecomm360 = tc.ecomm360;
            campaign.auto_tweet = tc.auto_tweet;
            campaign.timewarp = tc.timewarp;
            //
            campaignList.Add( campaign );
         }
         return campaignList;
      }

      // -----------------------------------------------------------------------------
      private campaignSegmentOptions FormatSegmentOptions( object segment_opts )
      {
         campaignSegmentOptions SegmentOptions = new campaignSegmentOptions();
         if ( segment_opts == null || segment_opts.GetType().IsArray ) return SegmentOptions;          // empty array for not segmented

         IDictionary seg_opts = segment_opts as IDictionary;
         SegmentOptions.match = seg_opts["match"].ToString();
         object[] opts_obj = seg_opts["conditions"] as object[];
         foreach ( object opt_obj in opts_obj )
         {
            IDictionary opts = opt_obj as IDictionary;
            campaignSegmentCondition cond = new campaignSegmentCondition();
            cond.field = opts["field"].ToString();
            cond.op = opts["op"].ToString();
            cond.value = opts["value"].ToString();
            if ( opts["extra"] != null )
               cond.extra = opts["extra"].ToString();
            SegmentOptions.conditions.Add( cond );
         }
         return SegmentOptions;
      }

      #endregion
   }
}
